package com.azt.data.utils;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.enums.EnumUtils;
import org.apache.commons.lang.enums.ValuedEnum;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;

import com.alibaba.fastjson.serializer.ValueFilter;
import com.xiaoleilu.hutool.util.CollectionUtil;
import com.xiaoleilu.hutool.util.StrUtil;

/**
 * 工具类
 */
public class CommonUtil {
	
	public static final String APPLIFIELD = "applifield";//应用领域数据字典父code
	
	public static final String BANKS = "banks"; //银行数据字典父code

    public static final String PUR_ASSET_TYPE = "purAssType";//采购商资质类型

    public static final String PRO_ASSET_TYPE = "proAssType";//采购商资质类型

	public static final List<String> specialArea = Arrays.asList("台湾省" , "香港特别行政区" , "澳门特别行政区");
	
	public static final String DEFUALT_USER_PASSWORD="123456";//默认用户密码
	
	public static final String DEFUALT_USER_ROLENAME="分公司管理员";//默认用户角色是分公司管理员
	
	public static final String MASTER_WEBSITE_URL="http://www.azt365.com";//现网：https://www.azt365.com

    static String[] mobileAgents = { "iphone", "android", "phone", "mobile", "wap", "netfront", "java", "opera mobi",
            "opera mini", "ucweb", "windows ce", "symbian", "series", "webos", "sony", "blackberry", "dopod", "nokia",
            "samsung", "palmsource", "xda", "pieplus", "meizu", "midp", "cldc", "motorola", "foma", "docomo",
            "up.browser", "up.link", "blazer", "helio", "hosin", "huawei", "novarra", "coolpad", "webos", "techfaith",
            "palmsource", "alcatel", "amoi", "ktouch", "nexian", "ericsson", "philips", "sagem", "wellcom", "bunjalloo",
            "maui", "smartphone", "iemobile", "spice", "bird", "zte-", "longcos", "pantech", "gionee", "portalmmm",
            "jig browser", "hiptop", "benq", "haier", "^lct", "320x320", "240x320", "176x220", "w3c ", "acs-", "alav",
            "alca", "amoi", "audi", "avan", "benq", "bird", "blac", "blaz", "brew", "cell", "cldc", "cmd-", "dang",
            "doco", "eric", "hipt", "inno", "ipaq", "java", "jigs", "kddi", "keji", "leno", "lg-c", "lg-d", "lg-g",
            "lge-", "maui", "maxo", "midp", "mits", "mmef", "mobi", "mot-", "moto", "mwbp", "nec-", "newt", "noki",
            "oper", "palm", "pana", "pant", "phil", "play", "port", "prox", "qwap", "sage", "sams", "sany", "sch-",
            "sec-", "send", "seri", "sgh-", "shar", "sie-", "siem", "smal", "smar", "sony", "sph-", "symb", "t-mo",
            "teli", "tim-", "tsm-", "upg1", "upsi", "vk-v", "voda", "wap-", "wapa", "wapi", "wapp", "wapr", "webc",
            "winw", "winw", "xda", "xda-", "googlebot-mobile" };

    /**
     * 分割List
     *
     * @param list 待分割的list
     * @param pageSize    每段list的大小
     * @return List<<List<T>>
     */
    public static <T> List<List<T>> splitList(List<T> list, int pageSize) {
        List<List<T>> listArray = new ArrayList<List<T>>();// 创建list数组,用来保存分割后的list
        if(CollectionUtil.isNotEmpty(list)) {
            int listSize = list.size(); // list的大小
            int page = (listSize + (pageSize - 1)) / pageSize;// 页数
            for (int i = 0; i < page; i++) { // 按照数组大小遍历
                List<T> subList = new ArrayList<T>(); // 数组每一位放入一个分割后的list
                for (int j = 0; j < listSize; j++) {// 遍历待分割的list
                    int pageIndex = ((j + 1) + (pageSize - 1)) / pageSize;// 当前记录的页码(第几页)
                    if (pageIndex == (i + 1)) {// 当前记录的页码等于要放入的页码时
                        subList.add(list.get(j)); // 放入list中的元素到分割后的list(subList)
                    }
                    if ((j + 1) == ((j + 1) * pageSize)) {// 当放满一页时退出当前循环
                        break;
                    }
                }
                listArray.add(subList);// 将分割后的list放入对应的数组的位中
            }
        }
        return listArray;
    }

    /**
     * 发送文本。使用UTF-8编码。
     */
    public static void renderText(HttpServletResponse response, String text) {
        render(response, "text/plain;charset=UTF-8", text);
    }

    /**
     * 发送json。使用UTF-8编码。
     */
    public static void renderJson(HttpServletResponse response, String text) {
        render(response, "application/json;charset=UTF-8", text);
    }

    /**
     * 发送xml。使用UTF-8编码。
     */
    public static void renderXml(HttpServletResponse response, String text) {
        render(response, "text/xml;charset=UTF-8", text);
    }

    /**
     * 发送内容。使用UTF-8编码。
     */
    public static void render(HttpServletResponse response, String contentType, String text) {
        response.setContentType(contentType);
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        PrintWriter writer = null;
        try {
            writer = response.getWriter();
            writer.write(text);
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(writer);
        }
    }

    public static Map getParameterMap(HttpServletRequest request) {
        // 参数Map
        Map properties = request.getParameterMap();
        // 返回值Map
        Map returnMap = new HashMap();
        Iterator entries = properties.entrySet().iterator();
        Map.Entry entry;
        String name = "";
        String value = "";
        while (entries.hasNext()) {
            entry = (Map.Entry) entries.next();
            name = (String) entry.getKey();
            Object valueObj = entry.getValue();
            if(null == valueObj){
                value = "";
            }else if(valueObj instanceof String[]){
                String[] values = (String[])valueObj;
                for(int i=0;i<values.length;i++){
                    value = values[i] + ",";
                }
                if(value.endsWith(",")) {
                    value = value.substring(0, value.length() - 1);
                }
            }else{
                value = valueObj.toString();
            }
            returnMap.put(name, value);
        }
        return returnMap;
    }

    public static int safeToInt(Object obj, int defaultValue) {
        int r = defaultValue;
        if (obj != null) {
            try {
                r = Integer.parseInt(String.valueOf(obj));
            } catch (Exception ex) {
            }
        }
        return r;
    }

    public static Integer safeToInteger(Object obj, Integer defaultValue) {
        Integer r = defaultValue;
        if (obj != null) {
            try {
                r = Integer.valueOf(String.valueOf(obj));
            } catch (Exception ex) {
            }
        }
        return r;
    }

    public static Integer safeToInteger(Object obj) {
        return safeToInteger(obj, null);
    }

    public static String safeToString(Object obj, String defaultValue) {
        String r = defaultValue;
        if (obj != null) {
            try {
                r = String.valueOf(obj);
            } catch (Exception ex) {}
        }
        return r;
    }

    public static String safeToString(Object obj) {
        return safeToString(obj, null);
    }

    public static Double safeToDouble(Object obj, Double defaultValue) {
        Double r = defaultValue;
        if (obj != null) {
            try {
                r = Double.valueOf(String.valueOf(obj));
            } catch (Exception ex) {
            }
        }
        return r;
    }

    public static Double safeToDouble(Object obj) {
        return safeToDouble(obj, null);
    }

    public static Boolean safeToBoolean(Object obj, Boolean defaultValue) {
        Boolean r = defaultValue;
        if (obj != null) {
            try {
                r = Boolean.valueOf(String.valueOf(obj));
            } catch (Exception ex) {
            }
        }
        return r;
    }

    public static boolean safeToBool(Object obj, boolean defaultValue) {
        boolean r = defaultValue;
        if (obj != null) {
            try {
                r = Boolean.parseBoolean(String.valueOf(obj));
            } catch (Exception ex) {
            }
        }
        return r;
    }

    public static Date safeToDate(Object obj, String format) {
        Date date = null;
        try {
            date = new SimpleDateFormat(format).parse(safeToString(obj, null));
        } catch (Exception e) {}
        return date;
    }

    public static String formatDate(Date date, String format) {
        String str = null;
        try {
            str = new SimpleDateFormat(format).format(date);
        } catch (Exception e) {}
        return str;
    }

    public static int getPageCount(int count, int size) {
        return count % size == 0 ? count / size : count / size + 1;
    }

    public static String getIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
        }
        if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) {
            InetAddress inet = null;
            try { // 根据网卡取本机配置的IP
                inet = InetAddress.getLocalHost();
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
            ip = inet.getHostAddress();
        }
        // 对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
        if (ip != null && ip.length() > 15) {
            if (ip.indexOf(",") > 0) {
                ip = ip.substring(0, ip.indexOf(","));
            }
        }
        return ip;
    }

    /**
     * 判断是否是ajax请求
     */
    public static boolean isAjax(HttpServletRequest request) {
    	String header = request.getHeader("X-Requested-With");
        return "XMLHttpRequest".equalsIgnoreCase(header);
    }

    /**
     * 获取之前请求的url，方便登录之后返回，只对非Ajax的GET请求有效
     * */
    public static String getPreUrl(HttpServletRequest request) {
        String url = "";
        if (!isAjax(request) && request.getMethod().equals("GET")) {
            StringBuilder redirect = new StringBuilder();
            redirect.append(request.getRequestURL().toString());
            String queryParams = StringUtils.trimToEmpty(request.getQueryString());
            if(StringUtils.isNotBlank(queryParams)){
                redirect.append("?").append(queryParams);
            }
            try {
                url += URLEncoder.encode(redirect.toString(), "utf-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return url;
    }

    /**
     * 获取登录的url
     * */
    public static String getLoginUrl(HttpServletRequest request) {
        String url = "/user/login";
        if(isMoblieBrowser(request)) {
            url = "/wechat/user/login";
        }
        String preUrl = getPreUrl(request);
        if(StringUtils.isNotBlank(preUrl)) {
            try {
                url += "?redirect=" + URLEncoder.encode(preUrl, "utf-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return url;
    }

    /**
     * 未授权处理：如果是非ajax的get请求，跳转回登录页面，如是ajax请求，返回401状态码
     * */
    public static void redirectToLogin(HttpServletRequest request, HttpServletResponse response) {
        if(isAjax(request)) {
            //ajax请求的话则401状态返回错误码
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            CommonUtil.renderJson(response, "401 Unauthorized");
        } else {
            String loginUrl = getLoginUrl(request);
            try {
                response.sendRedirect(loginUrl);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static Map getEnumMap(Class enumClass) {
        Map map = new LinkedHashMap();
        List<ValuedEnum> list = EnumUtils.getEnumList(enumClass);
        for(ValuedEnum valuedEnum : list) {
            map.put(valuedEnum.getValue() + "", valuedEnum.getName());
        }
        return map;
    }

    /**
     * 生成订单号[生成规则：yyMMddHHmmssSSS + 随机3位数字]
     * */
    public static String genOrderNumber() {
        return formatDate(new Date(), "yyMMddHHmmssSSS") + RandomStringUtils.randomNumeric(3);
    }

    public static String genPayNumber(String orderNumber, int batch) {
        return orderNumber + (batch < 10 ? "" + batch : batch) +  RandomStringUtils.randomNumeric(4);
    }

    /**
     * 生成分公司名称
     * */
    public static String branchCompanyName(String CompanyName, String branchName){
    	StringBuffer sb=new StringBuffer();
    	sb.append(CompanyName).append(branchName);
    	return sb.toString();
    }

    /**
     * 数字转汉字，如1 -> 一 (只能处理1~99之间的数)
     * */
    public static String num2CN(int num) {
        try {
            String[] array = {"一", "二", "三", "四", "五", "六", "七", "八", "九"};

            // 1
            if (num <= 9) {
                return array[num - 1];
            } else {
                //11
                String str = num + "";
                int num_1 = CommonUtil.safeToInteger(str.charAt(0));
                int num_2 = CommonUtil.safeToInteger(str.charAt(1));
                return (num_1 > 1 ? array[num_1 - 1] : "") + "十" + (num_2 > 0 ? array[num_2 - 1] : "");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 截取字符,超出部分显示...
     * */
    public static String getSimpleStr(String str, int maxLength) {
        if(StrUtil.isNotBlank(str) && str.length() > maxLength) {
            return str.substring(0, maxLength) + "...";
        }
        return str;
    }

    public static String getHiddenStr(String str, int length) {
        String hc = "";
        if(StrUtil.isNotBlank(str)) {
            if (str.length() > length) {
                hc = "*****" + str.substring(length);
            } else {
                for (int i = 0; i < str.length(); i++) {
                    hc += "*";
                }
            }
        }
        return hc;
    }

    /**
     * 重置sessionid，原session中的数据自动转存到新session中<br>
     * 登录前的请求一般都是http的，http是不安全的，假设用户登录前的JSESSIONID被人取得，
     * 如果登录后不变更JSESSIONID的话，即使登录请求是https的，该用户仍然会被他人冒充。
     */
    public static void resetSessionId(HttpServletRequest request) {
        HttpSession oldSession = request.getSession(false);
        if(oldSession != null && !oldSession.isNew()) {
            //首先将原session中的数据转移至一临时map中
            Map<String, Object> tempMap = new HashMap();
            Enumeration<String> sessionNames = oldSession.getAttributeNames();
            while (sessionNames.hasMoreElements()) {
                String sessionName = sessionNames.nextElement();
                tempMap.put(sessionName, oldSession.getAttribute(sessionName));
            }

            //注销原session，为的是重置sessionId
            oldSession.invalidate();

            //将临时map中的数据转移至新session
            HttpSession newSession = request.getSession(true);
            for (Map.Entry<String, Object> entry : tempMap.entrySet()) {
                newSession.setAttribute(entry.getKey(), entry.getValue());
            }
        }
    }

    public static String toUtf8String(String s) {

        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (c >= 0 && c <= 255) {
                sb.append(c);
            } else {
                byte[] b;
                try {
                    b = Character.toString(c).getBytes("utf-8");
                } catch (Exception ex) {
                    b = new byte[0];
                }
                for (int j = 0; j < b.length; j++) {
                    int k = b[j];
                    if (k < 0)
                        k += 256;
                    sb.append("%" + Integer.toHexString(k).toUpperCase());
                }
            }
        }
        return sb.toString();
    }

    /**
     * 根据不同浏览器将文件名中的汉字转为UTF8编码的串,以便下载时能正确显示另存的文件名.
     *
     * @param s
     *            原文件名
     * @return 重新编码后的文件名
     */
    public static String toUtf8String(String agent, String s) {
        try {
            boolean isFireFox = (agent != null && agent.toLowerCase().indexOf("firefox") != -1);
            boolean isSafari = (agent != null && agent.toLowerCase().indexOf("safari") != -1);
            if (isFireFox || isSafari) {
                s = new String(s.getBytes("UTF-8"), "ISO8859-1");
            } else {
                s = toUtf8String(s);
                if ((agent != null && agent.indexOf("MSIE") != -1)) {
                    // see http://support.microsoft.com/default.aspx?kbid=816868
                    if (s.length() > 150) {
                        // 根据request的locale 得出可能的编码
                        s = new String(s.getBytes("UTF-8"), "ISO8859-1");
                    }
                }
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return s;
    }


    /**
     * 对double数据进行取精度.
     * <p>
     * For example: <br>
     * double value = 100.345678; <br>
     * double ret = round(value,4,BigDecimal.ROUND_HALF_UP); <br>
     * ret为100.3457 <br>
     *
     * @param value
     *            double数据.
     * @param scale
     *            精度位数(保留的小数位数).
     * @param roundingMode
     *            精度取值方式.
     * @return 精度计算后的数据.
     */
    public static double round(double value, int scale, int roundingMode) {
        BigDecimal bd = new BigDecimal(value);
        bd = bd.setScale(scale, roundingMode);
        double d = bd.doubleValue();
        bd = null;
        return d;
    }

    /**
     * 是否是手机浏览器
     *
     * @return
     */
    public static boolean isMoblieBrowser(HttpServletRequest request) {
        String ua = request.getHeader("User-Agent");
        if (ua == null) {
            return false;
        }
        ua = ua.toLowerCase();
        for (String mobileAgent : mobileAgents) {
            if (ua.indexOf(mobileAgent) >= 0) {
                return true;
            }
        }
        return false;
    }

    /**
     * 是否是微信浏览器
     *
     * @return
     */
    public static boolean isWechatBrowser(HttpServletRequest request) {
        String ua = request.getHeader("User-Agent");
        if (ua == null) {
            return false;
        }
        ua = ua.toLowerCase();
        if (ua.indexOf("micromessenger") > 0) {
            return true;
        }
        return false;
    }
    
    
	/**
	 * @fieldName: filter
	 * @fieldType: ValueFilter
	 * @Description: JSON转换null为空格
	 */
    public static ValueFilter jsonfilter = new ValueFilter() {
		@Override
		public Object process(Object obj, String s, Object v) {
			if (v == null){
				return "";
			}
			return v;
		}
	};
	
/*    public static ValueFilter jsonDoublefilter = new ValueFilter() {
		@Override
		public Object process(Object obj, String s, Object v) {
			DecimalFormat dFormat = new DecimalFormat(".00");
			if (v != null){
				if(v instanceof Number){
					v=dFormat.format(v);
				}
			}
			return Float.valueOf(v.toString());
		}
	};*/
	
	
	
	//最近的几个月 需往前几个月
	public static String[] getLastMonths(int count,int fmonth,Date date){  
        String[] lastMonths = new String[count];  
          
        Calendar cal = Calendar.getInstance();
        cal.setTime(date); 
        cal.set(Calendar.MONTH, cal.get(Calendar.MONTH)+1+fmonth); //要先+1,才能把本月的算进去</span>  
        for(int i=0; i<count; i++){  
            cal.set(Calendar.MONTH, cal.get(Calendar.MONTH)-1); //逐次往前推1个月  
            lastMonths[count-i-1] = cal.get(Calendar.YEAR)+ "-" + String.format("%02d", (cal.get(Calendar.MONTH)+1));//格式化数字 
        }  
        return lastMonths;  
    }  
	
	//日期差几月
	   public static int getMiddleMonth(Date start, Date end) {  
	        if (start.after(end)) {  
	            Date t = start;  
	            start = end;  
	            end = t;  
	        }  
	        Calendar startCalendar = Calendar.getInstance();  
	        startCalendar.setTime(start);  
	        Calendar endCalendar = Calendar.getInstance();  
	        endCalendar.setTime(end);  
	        Calendar temp = Calendar.getInstance();  
	        temp.setTime(end);  
	        temp.add(Calendar.DATE, 1);  
	  
	        int year = endCalendar.get(Calendar.YEAR) - startCalendar.get(Calendar.YEAR);  
	        int month = endCalendar.get(Calendar.MONTH) - startCalendar.get(Calendar.MONTH);  
	  
	        if ((startCalendar.get(Calendar.DATE) == 1)&& (temp.get(Calendar.DATE) == 1)) {  
	            return year * 12 + month + 1;  
	        } else if ((startCalendar.get(Calendar.DATE) != 1) && (temp.get(Calendar.DATE) == 1)) {  
	            return year * 12 + month;  
	        } else if ((startCalendar.get(Calendar.DATE) == 1) && (temp.get(Calendar.DATE) != 1)) {  
	            return year * 12 + month;  
	        } else {  
	            return (year * 12 + month - 1) < 0 ? 0 : (year * 12 + month);  
	        }  
	    } 
	
	   public static String getLastDayOfMonth(int year, int month) {     
	         Calendar cal = Calendar.getInstance();     
	         cal.set(Calendar.YEAR, year);     
	         cal.set(Calendar.MONTH, month-1);     
	         cal.set(Calendar.DAY_OF_MONTH,cal.getActualMaximum(Calendar.DATE));  
	        return  new  SimpleDateFormat( "yyyy-MM-dd ").format(cal.getTime());  
	     }  
	
	public static void main(String[] args) {
		getLastDayOfMonth(2017,2);
	}
	
	
}